#include "CSession.h"
#include "CServer.h"
#include "MsgNode.h"
#include "LogicSystem.h"
#include "const.h"

#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <iostream>

CSession::CSession(boost::asio::io_context& ioc, CServer* server) 
	: m_socket(ioc), m_server(server), m_b_close(false), m_b_head_parse(false)
{
	// 为连接生成uuid
	boost::uuids::uuid uuid = boost::uuids::random_generator()();
	m_uuid = boost::uuids::to_string(uuid);

	m_recv_head_node = std::make_shared<MsgNode>(HEAD_TOTAL_LEN);
}

CSession::~CSession()
{
	std::cout << "destruct CSession......" << std::endl;
}

boost::asio::ip::tcp::socket& CSession::getSocket()
{
	return m_socket;
}

std::string& CSession::getUuid()
{
	return m_uuid;
}

void CSession::Close() {
	m_socket.close();
	m_b_close = true;
}

void CSession::start()
{
	asyncReadHead(HEAD_TOTAL_LEN);
}

std::shared_ptr<CSession> CSession::SharedSelf() {
	return shared_from_this();
}


void CSession::asyncReadHead(int total_len)
{
	auto self = shared_from_this();
	// 读取头部数据
	// 只有读完HEAD_TOTAL_LEN（4字节）之后，才会进行回调（或者说出现了错误）
	asyncReadFull(HEAD_TOTAL_LEN, [self, this](const boost::system::error_code& ec, size_t bytesTransfered) {
		try {
			if (ec) {
				std::cout << "handle read failed, error is " << ec.what() << std::endl;
				Close();
				m_server->clearSession(m_uuid);
				return;
			}

			// 准备读取数据，清空接收结点
			m_recv_head_node->Clear();

			// 读取头部msg_id
			memcpy(m_recv_head_node->m_data, m_data, bytesTransfered);
			unsigned short msg_id = 0;
			memcpy(&msg_id, m_recv_head_node->m_data, HEAD_ID_LEN);
			// 字节序转换
			msg_id = boost::asio::detail::socket_ops::network_to_host_short(msg_id);
			std::cout << "msg_id is " << msg_id << std::endl;
			// 头部id非法
			if (msg_id > MAX_LENGTH) {
				std::cout << "invalid msg_id is " << msg_id << std::endl;
				m_server->clearSession(m_uuid);

				return;
			}

			// 读取消息体的长度
			unsigned short msg_len = 0;
			memcpy(&msg_len, m_recv_head_node->m_data + HEAD_ID_LEN, HEAD_DATA_LEN);
			// 字节序的转换
			msg_len = boost::asio::detail::socket_ops::network_to_host_short(msg_len);
			std::cout << "msg_len is " << msg_len << std::endl;
			// 头部msg_len非法
			if (msg_len > MAX_LENGTH) {
				std::cout << "invalid msg_len is " << msg_len << std::endl;
				m_server->clearSession(m_uuid);

				return;
			}

			m_recv_msg_node = std::make_shared<RecvNode>(msg_len, msg_id);

			// 读数据体
			asyncReadBody(msg_len);
		}
		catch(std::exception& e) {
			std::cout << "Exception code is " << e.what() << std::endl;
		}
	});

}

void CSession::asyncReadBody(int length)
{
	auto self = shared_from_this();
	asyncReadFull(length, [self, this](const boost::system::error_code& ec, std::size_t bytesTransfered) {
		try {
			if (ec) {
				std::cout << "handle read failed, error is " << ec.what() << std::endl;
				Close();
				m_server->clearSession(m_uuid);
				return;
			}

			memcpy(m_recv_msg_node->m_data, m_data, bytesTransfered);
			m_recv_msg_node->m_cur_len += bytesTransfered;
			m_recv_msg_node->m_data[m_recv_msg_node->m_total_len] = '\0';
			std::cout << "receive data is " << m_recv_msg_node->m_data << std::endl;
			// 将消息投递到逻辑队列里面
			LogicSystem::getInstance()->postMsgToQue(std::make_shared<LogicNode>(shared_from_this(), m_recv_msg_node)); 
			// 继续监听头部的接收事件
			asyncReadHead(HEAD_TOTAL_LEN);
		}
		catch (std::exception& e) {
			std::cout << "Exception code is " << e.what() << std::endl;
		}
	});
}

void CSession::Send(std::string msg, unsigned short msg_id)
{
	std::lock_guard<std::mutex> lock(m_send_mtx);
	int send_que_size = m_send_queue.size();
	// 发送队列已满
	if (send_que_size > MAX_SENDQUE) {
		std::cout << "session : uuid = " << m_uuid << " send queue full,  size is " << send_que_size
			<< ", but MAX_SENDQUE = " << MAX_SENDQUE << std::endl;

		return;
	}

	m_send_queue.push( std::make_shared<SendNode>(msg.c_str(), msg.length(), msg_id) );
	auto& msg_node = m_send_queue.front();
	// 发送完数据包之后，才会进行回调操作
	boost::asio::async_write(m_socket, boost::asio::buffer(msg_node->m_data, msg_node->m_total_len),
		std::bind(&CSession::handleWrite, this, std::placeholders::_1, SharedSelf())
	);
}

void CSession::Send(char* msg, unsigned short max_len, unsigned short msg_id)
{
	std::lock_guard<std::mutex> lock(m_send_mtx);
	int send_que_size = m_send_queue.size();
	// 发送队列已满
	if (send_que_size > MAX_SENDQUE) {
		std::cout << "session : uuid = " << m_uuid << " send queue full,  size is " << send_que_size
			<< ", but MAX_SENDQUE = " << MAX_SENDQUE << std::endl;

		return;
	}

	// 构造成发送结点放入发送队列里面
	m_send_queue.push(std::make_shared<SendNode>(msg, max_len, msg_id));
	// 发送队列最初为0
	if (send_que_size > 0) {
		return;
	}

	auto& msg_node = m_send_queue.front();
	// 发送完数据包之后，才会进行回调操作
	boost::asio::async_write(m_socket, boost::asio::buffer(msg_node->m_data, msg_node->m_total_len),
		std::bind(&CSession::handleWrite, this, std::placeholders::_1, SharedSelf())
	);
}

void CSession::handleWrite(const boost::system::error_code& err, std::shared_ptr<CSession> shared_self)
{
	try {
		if (!err) {
			std::lock_guard<std::mutex> lock(m_send_mtx);
			// 弹出已发送的第一个结点数据
			m_send_queue.pop();
			if (!m_send_queue.empty()) {
				auto& msg_node = m_send_queue.front();
				// 如果队列不为空，则再次调用，直到队列中的数据全部发完为止
				boost::asio::async_write(m_socket, boost::asio::buffer(msg_node->m_data, msg_node->m_total_len), 
					std::bind(&CSession::handleWrite, this, std::placeholders::_1, shared_self)
				);
			}
		}
		else {
			std::cout << "handler write failed, error is " << err.what() << std::endl;
			Close();
			m_server->clearSession(m_uuid);
		}
	}
	catch (std::exception& e) {
		std::cout << "Exception code : " << e.what() << std::endl;
	}
}

// 读取完成长度
void CSession::asyncReadFull(size_t max_len, std::function<void(const boost::system::error_code&, size_t)> handler)
{
	::memset(m_data, 0, MAX_LENGTH);
	asyncReadLen(0, max_len, handler);
}

// 读取指定长度的字节数
void CSession::asyncReadLen(size_t read_len, size_t total_len, std::function<void(const boost::system::error_code&, size_t)> handler)
{
	auto self = shared_from_this();
	m_socket.async_read_some(boost::asio::buffer(m_data + read_len, total_len - read_len), 
		[read_len, total_len, handler, self](const boost::system::error_code& ec, size_t bytesTransfered) {
			if (ec) {
				// 出现错误直接调用回调函数
				handler(ec, read_len + bytesTransfered);
				return;
			} 

			if (read_len + bytesTransfered >= total_len) {
				// 头部长度足够，调用回调
				handler(ec, read_len + bytesTransfered);
				return;
			}

			// 未出现错误，并且长度不够需要继续读取
			self->asyncReadLen(read_len + bytesTransfered, total_len, handler);
		});
}

LogicNode::LogicNode(std::shared_ptr<CSession> session, std::shared_ptr<RecvNode> recvnode) : m_session(session), m_recvnode(recvnode)
{

}


